package loaderlib.loader
{
	import flash.events.Event;
	import flash.events.HTTPStatusEvent;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	import loaderlib.LocalCache.Cache;
	import loaderlib.progress.IProgressReporter;
	
	import mx.controls.Alert;

	/**
	 * RequestHeader is the real request, which emit loader to get resource.
	 * 
	 * there are at least one request link at the requestList attribute. the Requestheader hold the same request 
	 * (the same URI) linked at itself. 
	 * 
	 * @author TangZhen
	 * 
	 */
	public class RequestHeader extends Header implements IProgressReporter
	{	
		/**
		 * @private
		 * startTime is the Request send the load time( interval from the SWF start).
		 * 
		 * @default null 
		 */
		private var _startTime:int;
		
		/**
		 * @private
		 * finishTime is the time, when Request finish loaded resource( interval from the SWF start).
		 * 
		 * @default null 
		 */
		private var _finishTime:int;
		
		/**
		 * requestLoader is a loader instance, that actual load the resource. 
		 * 
		 * @default a new loader
		 */
		private var _requestLoader:URLLoader = new URLLoader();
		
		/**
		 * _url is the url of loader
		 * 
		 * @default null
		 */
		private var _url:String;
		
		private var _data:Object;
		
		private var _dataFormat:String;
		
		public var state:String;
		
		public var HTTPstatus:int;
		
		private var _finished:Boolean;
		
		public function RequestHeader()
		{
			super();
			this.linkName = "requestQueue";
		}
		
		
		public function initRequest(request:Request):void
		{
			this._url = request.url
			this._dataFormat = request.dataFormat;
////			if(!this.getFromCache())
//			{
//				this.start();
//			}
		}
		
		public function start():void
		{
			this.getFromNetwork()
		}
		
		public function get finished():Boolean
		{
			return this._finished;
		}
		
		override public function get info():XML
		{
			var info:XML = <requestHeader></requestHeader>
			info.appendChild(<url>{this._url}</url>)
			info.appendChild(<loaded>{this._requestLoader.bytesLoaded}</loaded>)
			info.appendChild(<total>{this._requestLoader.bytesTotal}</total>)
			info.appendChild(<finished>{this._finished}</finished>)
			return info
		}
		
		override public function get bytesLoaded():Number
		{
			return this._requestLoader?this._requestLoader.bytesLoaded:0
		}
		
		override public function get bytesTotal():Number
		{
			return this._requestLoader?this._requestLoader.bytesTotal:0
		}
		
		
		public function getFromCache():Boolean
		{
			var cache:Cache = new Cache(this._url)
			if(cache.cachedObject && cache.cachedObject.data.hasOwnProperty("data"))
			{
				this._data = cache.cachedObject.data.data
				this._dataFormat = cache.cachedObject.data.dataFormat
				return true
			}
			return false
		}
		
		public function getFromNetwork():void
		{
			this._requestLoader.addEventListener(Event.ACTIVATE, this.stateChange)
			this._requestLoader.addEventListener(Event.INIT,this.stateChange)
			this._requestLoader.addEventListener(Event.OPEN,this.stateChange)
			this._requestLoader.addEventListener(HTTPStatusEvent.HTTP_STATUS,this.HTTPStatusChange)
			this._requestLoader.addEventListener(Event.COMPLETE,this.loaderFinished)
			this._requestLoader.addEventListener(IOErrorEvent.IO_ERROR,this.loaderError)
			this._requestLoader.dataFormat = this._dataFormat
			this._requestLoader.load(new URLRequest(this._url))		
		}
		
		private function loaderError(event:Event):void
		{
			mx.controls.Alert.show(event.toString())
		}
		
		private function stateChange(event:Event):void
		{
			this.state = event.type;
		}
		
		private function HTTPStatusChange(event:HTTPStatusEvent):void
		{
			this.HTTPstatus = event.status
		}
		
		private function loaderFinished(event:Event):void
		{
			this._data = this._requestLoader.data
			var reportFunction:Function = function(testRequest:Request):void
			{
				testRequest.finish(this._data)
			}
			var cache:Cache = new Cache(this._url)
			if(cache.valid)
			{
				cache.cachedObject.data.data = this._data
				cache.cachedObject.data.dataFormat = this._dataFormat
				cache.cachedObject.flush()
			}
			this.forEach(reportFunction)
			this._finished = true
		}
		
		override internal function appendRequest(request:Request):Boolean
		{
			var appendBool:Boolean = super.appendRequest(request);
			if(appendBool)
			{
				request.requestHeader = this;
				if(this._data)
				{
					request.finish(this._data)
				}
			}
			return appendBool
		}
		
		public static function initHeader(request:Request):RequestHeader
		{
			var header:RequestHeader = new RequestHeader()
			header.initRequest(request)
			header.appendRequest(request);
			return header;
		}
		
	}
}